/***************************************************************************
 *   Copyleft 2006-2007 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#ifndef __DYNAMICARRAY2D_H__
#define __DYNAMICARRAY2D_H__

#include <memory.h>
#include <exception>
#include "../Types/Types.h"

template <class T>
class DynamicArray2D {
private:
	T **mTable;
	cInt mRowSize;
	cInt mColSize;

	cVoid Init(cInt n, cInt m);
public:
	/**************************************************************
    * Constructors                                                *
    ***************************************************************/
	DynamicArray2D();
	DynamicArray2D(const DynamicArray2D& v);
	DynamicArray2D(cInt n, cInt m);
	~DynamicArray2D();

	/**************************************************************
    * Operators                                                   *
    ***************************************************************/
	T& operator()(cInt i, cInt j);
	DynamicArray2D<T>& operator=(const DynamicArray2D<T>& v);

	/**************************************************************
    * Other helpful functions                                     *
    ***************************************************************/
	cVoid Clear();
	cInt GetRowSize();
	cInt GetColSize();
};                                                                 

/**************************************************************
* Constructors                                                *
***************************************************************/
template <class T>
DynamicArray2D<T>::DynamicArray2D() : mTable(cNull), mRowSize(0), mColSize(0) { }

template <class T>
DynamicArray2D<T>::DynamicArray2D(const DynamicArray2D& v) {
	Init(v.mRowSize, v.mColSize);
	for (cInt i = 0; i < mRowSize; i++) {
		memcpy(mTable[i], v.mTable[i], sizeof(T) * mColSize);
	}
}

template <class T>
DynamicArray2D<T>::DynamicArray2D(cInt n, cInt m) : mTable(cNull) {
	Init(n, m);
}

template <class T>
DynamicArray2D<T>::~DynamicArray2D() {
	Clear();
}

    
/**************************************************************
* Operators                                                   *
***************************************************************/
template <class T>
cVoid DynamicArray2D<T>::Init(cInt n, cInt m) {
	mRowSize = n;
	mColSize = m;

	mTable = new T*[mRowSize];
	for (cInt i = 0; i < mRowSize; i++) {
		mTable[i] = new T[mColSize];
	}
}

template <class T>
T& DynamicArray2D<T>::operator()(cInt i, cInt j) {
	if (i < 0 || i >= mRowSize) {
		throw std::exception();
	}
	if (j < 0 || j >= mColSize) {
		throw std::exception();
	}

	return mTable[i][j];
}

template <class T>
DynamicArray2D<T>& DynamicArray2D<T>::operator=(const DynamicArray2D<T>& v) {
	Clear();
	Init(v.mRowSize, v.mColSize);

	for (cInt i = 0; i < mRowSize; i++) {
		memcpy(mTable[i], v.mTable[i], sizeof(T) * mColSize);
	}

	return *this;
}

/**************************************************************
* Other helpful functions                                     *
***************************************************************/
template <class T>
cVoid DynamicArray2D<T>::Clear() {
	if (mTable != cNull)	{
		for (cInt i = 0; i < mRowSize; i++) {
			delete []mTable[i];
		}
		delete []mTable;
	}

	mTable = cNull;
	mRowSize = 0;
	mColSize = 0;
}

template <class T>
cInt DynamicArray2D<T>::GetRowSize() {
	return mRowSize;
}

template <class T>
cInt DynamicArray2D<T>::GetColSize() {
	return mColSize;
}

#endif // __DYNAMICARRAY2D_H__